/**
 * Copyright (C), 2018 store
 * Encoding: UTF-8
 * Date: 19-12-10 下午3:20
 * History:
 */
package com.swak.frame.excel.csv;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.core.io.Resource;

import com.swak.frame.excel.ExcelUtils;
import com.swak.frame.excel.bo.CellObject;
import com.swak.frame.excel.bo.RowObject;
import com.swak.frame.excel.bo.SheetObject;
import com.swak.frame.excel.exception.ExcelException;
import com.swak.frame.logger.SwakLoggerFactory;
import com.swak.frame.util.StringPool;

import au.com.bytecode.opencsv.CSVReader;


/**
 * CvsHandlerFactory.java
 *
 * @author ColleyMa
 * @version 19-12-10 下午3:20
 */
public class CsvHandlerFactory {
    private final Logger logger = SwakLoggerFactory.getLogger(getClass());

    public SheetObject getInputValuesByCvs(File file, String fileEncoding) {
        return handerCvsObject(file, fileEncoding);
    }

    public SheetObject getInputValuesByCvs(File file) {
        return handerCvsObject(file, StringPool.UTF8);
    }

    public SheetObject getInputValuesByCvs(Resource location, String fileEncoding) {
        try {
            return getInputValuesByCvs(location.getFile(), fileEncoding);
        } catch (IOException e) {
            logger.error("open csv file error!", e);
        }

        return null;
    }

    public SheetObject getInputValuesByCvs(Resource location) {
        try {
            return getInputValuesByCvs(location.getFile());
        } catch (IOException e) {
            logger.error("open csv file error!", e);
        }

        return null;
    }

    public Map<String, String> getHearder(String[] header) {
        Map<String, String> headerMap = new HashMap<String, String>();

        for (int i = 0; i < header.length; i++) {
            String propName = header[i];
            propName = ExcelUtils.matcherLastValue(propName, null);

            if (!StringUtils.isEmpty(propName)) {
                headerMap.put(String.valueOf(i), propName);
            }
        }

        return headerMap;
    }

    public SheetObject handerCvsObject(File file, String fileEncoding) {
        SheetObject sheetObject = new SheetObject();
        CSVReader reader = null;

        try {
            reader =
                new CSVReader(new InputStreamReader(new FileInputStream(file), fileEncoding), ',');

            // 先读取头部
            String[] headerArr = reader.readNext(); // 用readnext读取之后就不存在于stream中了

            Map<String, String> header = getHearder(headerArr);

            if ((header.size() == 0) || (header.size() < 2)) {
                throw new RuntimeException("上传的csv缺少头部信息！"); // errorId=3CMS_EXCEL_TEMPLETE_FORMAT
            }

            sheetObject.setHeader(header);

            List<String[]> rowlist = reader.readAll(); // 此时读取的已经是第二行了

            List<RowObject> rowObjects = handerRowData(header, rowlist);
            sheetObject.setSheetData(rowObjects);
        } catch (Exception e) {
            logger.error("获取数据报错!", e);

            if (e instanceof ExcelException) {
                throw new ExcelException(e.getMessage());
            } else {
                throw new ExcelException("获取csv信息报错！", e);
            }
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    logger.error("CSVReader close error", e);
                }
            }
        }

        return sheetObject;
    }

    public List<RowObject> handerRowData(Map<String, String> header, List<String[]> rowlist)
        throws ExcelException {
        int colCount = header.size();
        List<RowObject> rowDatas = new ArrayList<RowObject>();

        for (int row = 0; row < rowlist.size(); row++) {
            RowObject rowData = new RowObject();
            rowData.setRow(row + 1);

            String[] cellList = rowlist.get(row);
            List<CellObject> cellDatas = new ArrayList<CellObject>();

            for (int col = 0; col < colCount; col++) {
                CellObject cellData = new CellObject();
                cellData.setColum(col);

                String cellVal = cellList[col];
                cellData.setCellVal(cellVal);

                String propName = header.get(String.valueOf(col));
                cellData.setPropName(propName);
                cellDatas.add(cellData);
            }

            rowData.setRowData(cellDatas);
            rowDatas.add(rowData);
        }

        return rowDatas;
    }
}
